#[macro_use]
extern crate getset;
#[macro_use]
extern crate lazy_static;
pub mod jwt;
pub mod password;
pub mod request_model;
use state::Container;
use std::sync::{Arc, Mutex};

use crate::request_model::RequestModel;
/*不能重复赋值  否则第二次将赋值不进去  这是一个单例池*/
pub(crate) static APPLICATION_CONTEXT: Container![Send + Sync] = <Container![Send + Sync]>::new();

pub trait ReqContext {
  fn get_request_model() -> Option<Arc<Mutex<RequestModel>>>;
  fn set_request_model(model: RequestModel);
}

pub trait AppContext {
  fn get_service<T: 'static>() -> Option<Arc<Mutex<T>>>;
  fn set_service<T: Send + Sync + 'static>(service: T);
}
#[derive(Clone, Default)]
pub struct ApplicationContext {}

impl AppContext for ApplicationContext {
  fn get_service<T: 'static>() -> Option<Arc<Mutex<T>>> {
    let service = APPLICATION_CONTEXT.try_get::<Arc<Mutex<T>>>();
    match service {
      None => None,
      Some(s) => Some(Arc::clone(s)),
    }
  }
  fn set_service<T: Send + Sync + 'static>(ser: T){
    let mutex = Arc::new(Mutex::new(ser));
    APPLICATION_CONTEXT.set(mutex);
  }
}

#[derive(Clone, Default)]
pub struct RequestContext {}

impl ReqContext for RequestContext {
  fn get_request_model() -> Option<Arc<Mutex<RequestModel>>> {
    let local = APPLICATION_CONTEXT.try_get_local::<Arc<Mutex<RequestModel>>>();
    match local {
      None => {
        let attachment = RequestModel::default();
        let mutex = Arc::new(Mutex::new(attachment));
        let mutex_clone = Arc::clone(&mutex);
        APPLICATION_CONTEXT.set_local(move || {
          return Arc::clone(&mutex_clone);
        });
        Some(Arc::clone(&mutex))
      }
      Some(attachment) => Some(attachment.clone()),
    }
  }
  fn set_request_model(model: RequestModel) {
    let local = APPLICATION_CONTEXT.try_get_local::<Arc<Mutex<RequestModel>>>();
    match local {
      None => {
        let mutex = Arc::new(Mutex::new(model));
        let mutex_clone = Arc::clone(&mutex);
        APPLICATION_CONTEXT.set_local(move || {
          return Arc::clone(&mutex_clone);
        });
      }
      Some(attachment) => {
        let mut mode = attachment.lock().unwrap();
        mode.setDataForRequestModel(model)
      }
    }
  }
}
